/**
 * 错误监控服务
 * 用于捕获、记录和报告JavaScript运行时错误
 */

import { message, notification } from 'antd';

class ErrorMonitor {
  constructor() {
    this.errors = [];
    this.maxErrors = 100; // 最多保存100个错误
    this.isInitialized = false;
    this.errorCallback = null;
    
    // 初始化错误监控
    this.init();
  }

  /**
   * 初始化错误监控
   */
  init() {
    if (this.isInitialized) return;

    // 捕获控制台警告和错误
    this.interceptConsole();

    // 捕获未处理的Promise拒绝
    window.addEventListener('unhandledrejection', (event) => {
      this.handleError({
        type: 'unhandledrejection',
        message: event.reason?.message || 'Unhandled Promise Rejection',
        stack: event.reason?.stack || '',
        timestamp: new Date().toISOString(),
        url: window.location.href,
        userAgent: navigator.userAgent,
        promise: event.promise,
        reason: event.reason
      });
    });

    // 捕获全局JavaScript错误
    window.addEventListener('error', (event) => {
      this.handleError({
        type: 'javascript',
        message: event.message,
        filename: event.filename,
        lineno: event.lineno,
        colno: event.colno,
        stack: event.error?.stack || '',
        timestamp: new Date().toISOString(),
        url: window.location.href,
        userAgent: navigator.userAgent,
        error: event.error
      });
    });

    // 捕获资源加载错误
    window.addEventListener('error', (event) => {
      if (event.target !== window) {
        this.handleError({
          type: 'resource',
          message: `Failed to load resource: ${event.target.src || event.target.href}`,
          element: event.target.tagName,
          source: event.target.src || event.target.href,
          timestamp: new Date().toISOString(),
          url: window.location.href,
          userAgent: navigator.userAgent
        });
      }
    }, true);

    // 监听网络状态
    window.addEventListener('online', () => {
      this.logInfo('网络连接已恢复');
    });

    window.addEventListener('offline', () => {
      this.logWarning('网络连接已断开');
    });

    this.isInitialized = true;
    console.log('🔍 错误监控系统已启动');
  }

  /**
   * 拦截控制台输出
   */
  interceptConsole() {
    // 保存原始的控制台方法
    const originalConsole = {
      warn: console.warn,
      error: console.error,
      log: console.log
    };

    // 拦截 console.warn
    console.warn = (...args) => {
      const message = args.map(arg => 
        typeof arg === 'object' ? JSON.stringify(arg) : String(arg)
      ).join(' ');
      
      // 检查是否是React/Ant Design警告
      if (message.includes('Warning:') || message.includes('[antd:')) {
        this.addError({
          type: 'console-warning',
          message: message,
          timestamp: new Date().toISOString(),
          url: window.location.href,
          source: 'console.warn'
        });
      }
      
      // 调用原始方法
      originalConsole.warn.apply(console, args);
    };

    // 拦截 console.error
    console.error = (...args) => {
      const message = args.map(arg => 
        typeof arg === 'object' ? JSON.stringify(arg) : String(arg)
      ).join(' ');
      
      this.addError({
        type: 'console-error',
        message: message,
        timestamp: new Date().toISOString(),
        url: window.location.href,
        source: 'console.error'
      });
      
      // 调用原始方法
      originalConsole.error.apply(console, args);
    };

    // 保存原始方法的引用，以便后续可能的恢复
    this.originalConsole = originalConsole;
  }

  /**
   * 处理错误
   */
  handleError(errorInfo) {
    // 添加到错误列表
    this.addError(errorInfo);
    
    // 控制台输出
    console.error('🚨 捕获到错误:', errorInfo);
    
    // 显示用户友好的错误提示
    this.showUserNotification(errorInfo);
    
    // 调用回调函数（如果设置了）
    if (this.errorCallback) {
      try {
        this.errorCallback(errorInfo);
      } catch (callbackError) {
        console.error('错误回调函数执行失败:', callbackError);
      }
    }
    
    // 可以在这里添加错误上报逻辑
    this.reportError(errorInfo);
  }

  /**
   * 添加错误到列表
   */
  addError(errorInfo) {
    this.errors.unshift({
      id: Date.now() + Math.random(),
      ...errorInfo
    });
    
    // 保持错误列表大小
    if (this.errors.length > this.maxErrors) {
      this.errors = this.errors.slice(0, this.maxErrors);
    }
  }

  /**
   * 显示用户友好的错误通知
   */
  showUserNotification(errorInfo) {
    const isDevelopment = process.env.NODE_ENV === 'development';
    
    switch (errorInfo.type) {
      case 'javascript':
        if (isDevelopment) {
          notification.error({
            message: 'JavaScript错误',
            description: `${errorInfo.message}\n位置: ${errorInfo.filename}:${errorInfo.lineno}`,
            duration: 8,
            placement: 'topRight'
          });
        } else {
          message.error('系统出现异常，请刷新页面重试');
        }
        break;
        
      case 'unhandledrejection':
        if (isDevelopment) {
          notification.error({
            message: 'Promise错误',
            description: errorInfo.message,
            duration: 6,
            placement: 'topRight'
          });
        } else {
          message.error('网络请求失败，请检查网络连接');
        }
        break;
        
      case 'resource':
        if (isDevelopment) {
          notification.warning({
            message: '资源加载失败',
            description: errorInfo.message,
            duration: 4,
            placement: 'topRight'
          });
        }
        break;
        
      default:
        if (isDevelopment) {
          notification.info({
            message: '系统信息',
            description: errorInfo.message,
            duration: 3,
            placement: 'topRight'
          });
        }
    }
  }

  /**
   * 错误上报（可以发送到服务器）
   */
  reportError(errorInfo) {
    // 这里可以实现错误上报逻辑
    // 例如发送到错误监控服务、日志服务等
    
    // 示例：发送到控制台（开发环境）
    if (process.env.NODE_ENV === 'development') {
      console.group('📊 错误报告');
      console.log('错误类型:', errorInfo.type);
      console.log('错误信息:', errorInfo.message);
      console.log('发生时间:', errorInfo.timestamp);
      console.log('页面URL:', errorInfo.url);
      console.log('用户代理:', errorInfo.userAgent);
      if (errorInfo.stack) {
        console.log('错误堆栈:', errorInfo.stack);
      }
      console.groupEnd();
    }
    
    // 生产环境可以发送到服务器
    // fetch('/api/errors', {
    //   method: 'POST',
    //   headers: { 'Content-Type': 'application/json' },
    //   body: JSON.stringify(errorInfo)
    // }).catch(err => console.error('错误上报失败:', err));
  }

  /**
   * 手动记录错误
   */
  logError(message, error = null) {
    this.handleError({
      type: 'manual',
      message,
      stack: error?.stack || '',
      timestamp: new Date().toISOString(),
      url: window.location.href,
      userAgent: navigator.userAgent,
      error
    });
  }

  /**
   * 记录警告
   */
  logWarning(message) {
    console.warn('⚠️ 警告:', message);
    this.addError({
      type: 'warning',
      message,
      timestamp: new Date().toISOString(),
      url: window.location.href
    });
  }

  /**
   * 记录信息
   */
  logInfo(message) {
    console.info('ℹ️ 信息:', message);
    this.addError({
      type: 'info',
      message,
      timestamp: new Date().toISOString(),
      url: window.location.href
    });
  }

  /**
   * 获取所有错误
   */
  getErrors() {
    return [...this.errors];
  }

  /**
   * 获取特定类型的错误
   */
  getErrorsByType(type) {
    return this.errors.filter(error => error.type === type);
  }

  /**
   * 清空错误列表
   */
  clearErrors() {
    this.errors = [];
    console.log('🧹 错误列表已清空');
  }

  /**
   * 设置错误回调函数
   */
  setErrorCallback(callback) {
    this.errorCallback = callback;
  }

  /**
   * 获取错误统计
   */
  getErrorStats() {
    const stats = {
      total: this.errors.length,
      byType: {},
      recent: this.errors.slice(0, 10)
    };
    
    this.errors.forEach(error => {
      stats.byType[error.type] = (stats.byType[error.type] || 0) + 1;
    });
    
    return stats;
  }

  /**
   * 导出错误日志
   */
  exportErrors() {
    const data = {
      timestamp: new Date().toISOString(),
      userAgent: navigator.userAgent,
      url: window.location.href,
      errors: this.errors
    };
    
    const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `error-log-${new Date().toISOString().slice(0, 10)}.json`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
    
    message.success('错误日志已导出');
  }

  /**
   * 性能监控
   */
  monitorPerformance() {
    if ('performance' in window) {
      const navigation = performance.getEntriesByType('navigation')[0];
      if (navigation) {
        const loadTime = navigation.loadEventEnd - navigation.loadEventStart;
        if (loadTime > 3000) { // 超过3秒认为是慢加载
          this.logWarning(`页面加载时间过长: ${loadTime}ms`);
        }
      }
    }
  }

  /**
   * 销毁错误监控，清理事件监听器
   */
  destroy() {
    if (!this.isInitialized) return;
    
    // 这里可以移除事件监听器，但由于我们使用的是全局监听器
    // 在实际应用中通常不需要移除，因为它们应该在整个应用生命周期中保持活跃
    // 如果确实需要移除，需要保存对监听器函数的引用
    
    this.isInitialized = false;
    this.errorCallback = null;
    console.log('🔍 错误监控系统已停止');
  }
}

// 创建全局实例
const errorMonitor = new ErrorMonitor();

// 导出实例和类
export default errorMonitor;
export { ErrorMonitor };